package com.sawyerqiu.ui;

import com.alibaba.excel.util.DateUtils;
import com.alibaba.excel.util.StringUtils;
import com.sawyerqiu.constant.DateConstant;
import com.sawyerqiu.constant.FileConstant;
import com.sawyerqiu.model.GoodExcelData;
import com.sawyerqiu.model.OrderExcelData;
import com.sawyerqiu.model.Result;
import com.sawyerqiu.model.StoreNameSheetData;
import com.sawyerqiu.ui.plugin.JDateChooser;
import com.sawyerqiu.ui.plugin.MultiComboBox;
import com.sawyerqiu.util.DateUtil;
import com.sawyerqiu.util.ExcelUtil;
import com.sawyerqiu.util.WordUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.*;
import java.util.function.BiConsumer;

/**
 * @author : SawyerQiu
 * @date : 2024/7/30 10:57
 */
public class OrderOutputPanel extends JPanel {

    private Date date = null;
    private JLabel dateLabel;
    private JButton dateButton;

    private Date date1 = null;
    private JLabel dateLabel1;
    private JButton dateButton1;


    private String path = "";
    private JLabel filePathLabel;
    private JButton filePathButton;

    private String targetPath = "";
    private JLabel targetPathLabel;
    private JButton targetPathButton;

    private JLabel selectBoxLabel;
    private MultiComboBox<String> selectBox;

    private JButton start;

    private JButton settleBtn;

    ///
    private List<OrderExcelData> allData;

    private Map<String, StoreNameSheetData> storeNameDataMap;

    private Map<String, List<OrderExcelData>> address2OrderExcelDataList;

    public OrderOutputPanel() {

        dateLabel = new JLabel();
        dateLabel.setText("开始日期： ");
        dateButton = new JButton("请选择日期（不选则全生成）");

        dateLabel1 = new JLabel();
        dateLabel1.setText("结束日期： ");
        dateButton1 = new JButton("请选择日期（不选则全生成）");

        filePathLabel = new JLabel();
        filePathLabel.setText("文件： ");
        filePathButton = new JButton("请选择xlxs");

        targetPathLabel = new JLabel();
        targetPathLabel.setText("目标路径： ");
        targetPathButton = new JButton("请选择生成的路径");

        selectBoxLabel = new JLabel();
        selectBoxLabel.setText("目标数据： ");
        selectBox = new MultiComboBox<>();

        start = new JButton("开始生成PNG送货单");

        settleBtn = new JButton("开始生成PNG月结明细");

        addDateButtonAction(dateButton, (flag, selectDate) -> {
            if (!flag) {
                clearDate();
                return;
            }

            this.date = selectDate;
            this.dateLabel.setText("开始日期： " + DateUtils.format(selectDate, "yyyy/MM/dd"));

            if (this.date1 == null) {
                this.date1 = selectDate;
                this.dateLabel1.setText("结束日期： " + DateUtils.format(selectDate, "yyyy/MM/dd"));
            }


            if (!CollectionUtils.isEmpty(allData)) {
                refreshSelectBoxDatum();
            }
        });
        addDateButtonAction(dateButton1, (flag, selectDate) -> {
            if (!flag) {
                clearDate();
                return;
            }

            this.date1 = selectDate;
            this.dateLabel1.setText("结束日期： " + DateUtils.format(selectDate, "yyyy/MM/dd"));

            if (this.date == null) {
                this.date = selectDate;
                this.dateLabel.setText("开始日期： " + DateUtils.format(selectDate, "yyyy/MM/dd"));
            }

            if (!CollectionUtils.isEmpty(allData)) {
                refreshSelectBoxDatum();
            }
        });

        MainUi.addFileChooserAction(filePathButton, file -> {
            if (!file.isFile()
                    || !file.getPath().endsWith("xlsx")) {
                return Result.valueOfFail("请选择正确的xlsx文件");
            }

            return Result.getSUCCESS();
        }, file -> {
            path = file.getPath();
            filePathLabel.setText("文件： " + path);

            if (targetPath.equals("")) {
                targetPath = file.getParent();
                targetPathLabel.setText("目标路径： " + targetPath);
            }

            loadOrderExcelData();
            loadStoreNameData();

            refreshSelectBoxDatum();
        });

        MainUi.addFileChooserAction(targetPathButton, file -> {
            if (file.isFile()) {
                return Result.valueOfFail("请选择正确的文件夹");
            }

            return Result.getSUCCESS();
        }, file -> {
            targetPath = file.getPath();
            targetPathLabel.setText("目标路径： " + targetPath);
        });

        addStartAction(start);
        addSettleAction(settleBtn);

        // 布局
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel.add(dateLabel);
        panel.add(dateButton);

        JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel1.add(dateLabel1);
        panel1.add(dateButton1);

        JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel2.add(filePathLabel);
        panel2.add(filePathButton);

        JPanel panel3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel3.add(targetPathLabel);
        panel3.add(targetPathButton);

        JPanel panel4 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel4.add(selectBoxLabel);
        panel4.add(selectBox);

        JPanel panel5 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel5.add(start);

        JPanel panel6 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panel6.add(settleBtn);

        setLayout(new FlowLayout(FlowLayout.CENTER, 5, 10));

        add(panel);
        add(panel1);
        add(panel2);
        add(panel3);
        add(panel4);
        add(panel5);
        add(panel6);
    }

    private void loadOrderExcelData() {
        allData = new ArrayList<>();

        ExcelUtil.readDo(path, OrderExcelData.class,
                orderExcelData -> true,
                orderExcelData -> allData.add(orderExcelData));
    }

    private void loadStoreNameData() {
        storeNameDataMap = new HashMap<>();

        ExcelUtil.readDo(path, FileConstant.STORE_NAME_SHEET_NAME, StoreNameSheetData.class,
                data -> true,
                data -> storeNameDataMap.put(data.getName(), data));
    }

    private void refreshSelectBoxDatum() {
        address2OrderExcelDataList = new HashMap<>();

        allData.forEach(orderExcelData -> {
            if (date != null && orderExcelData.getDate().getTime() < date.getTime()) {
                return;
            }

            if (date1 != null && date1.getTime() < orderExcelData.getDate().getTime()) {
                return;
            }

            String storeName = getStoreNameByBuyer(orderExcelData.getBuyer());
            if(StringUtils.isEmpty(storeName)){
                return;
            }

            address2OrderExcelDataList.computeIfAbsent(storeName, k -> new ArrayList<>())
                    .add(orderExcelData);
        });

        String[] selectItems = address2OrderExcelDataList.keySet().toArray(new String[0]);
        selectBox.setDatum(selectItems);

        repaint();
    }

    private String getStoreNameByBuyer(String buyer) {
        StoreNameSheetData storeNameSheetData = storeNameDataMap.getOrDefault(buyer, null);
        return storeNameSheetData == null ? StringUtils.EMPTY : storeNameSheetData.getStoreName();
    }

    private void clearDate() {
        if (date != null) {
            date = null;
            dateLabel.setText("开始日期： ");
        }

        if (date1 != null) {
            date1 = null;
            dateLabel1.setText("结束日期： ");
        }
    }

    private void addDateButtonAction(JButton dateButton, BiConsumer<Boolean, Date> dateConsumer) {
        dateButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Calendar instance = Calendar.getInstance();
                instance.setTimeInMillis(date == null ? DateUtil.getMorningTimeMillis() : date.getTime());

                JDateChooser jDateChooser = new JDateChooser(instance);
                jDateChooser.setVisible(true);

                dateConsumer.accept(jDateChooser.getFlag(), jDateChooser.getDateObject());
            }
        });
    }

    private void addStartAction(JButton start) {
        start.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                checkParamDo(() -> start());
            }
        });
    }

    private void addSettleAction(JButton settleBtn) {
        settleBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                checkParamDo(() -> settle());
            }
        });
    }

    private void checkParamDo(Runnable runnable) {
        if (path.equals("")) {
            JOptionPane.showMessageDialog(OrderOutputPanel.this,
                    "请选择正确的xlsx文件", "warn", JOptionPane.WARNING_MESSAGE);
        } else if (targetPath.equals("")) {
            JOptionPane.showMessageDialog(OrderOutputPanel.this,
                    "请选择正确的目标文件夹", "warn", JOptionPane.WARNING_MESSAGE);
        } else if (!checkTime()) {
            JOptionPane.showMessageDialog(OrderOutputPanel.this,
                    "请输入正确的时间区间", "warn", JOptionPane.WARNING_MESSAGE);
        } else if (MapUtils.isEmpty(address2OrderExcelDataList)) {
            JOptionPane.showMessageDialog(this,
                    "没有找到数据", "tip", JOptionPane.INFORMATION_MESSAGE);

        } else {
            runnable.run();
        }
    }

    private void start() {
        Map<Date, Map<String, List<OrderExcelData>>> dateOrderMap = new HashMap<>();
        // 选中的数据
        selectBox.walkSelectedValues(address -> {
            List<OrderExcelData> orderExcelDatum = address2OrderExcelDataList.get(address);
            if (CollectionUtils.isEmpty(orderExcelDatum)) {
                return;
            }
            orderExcelDatum.forEach(orderExcelData ->
                    dateOrderMap
                            .computeIfAbsent(orderExcelData.getDate(), k -> new HashMap<>())
                            .computeIfAbsent(orderExcelData.getBuyer(), k -> new ArrayList<>())
                            .add(orderExcelData));
        });

        // 没有选就尝试拿全部
        if (MapUtils.isEmpty(dateOrderMap)) {
            Collection<List<OrderExcelData>> values = address2OrderExcelDataList.values();
            for (List<OrderExcelData> list : values) {
                list.forEach(orderExcelData ->
                        dateOrderMap
                                .computeIfAbsent(orderExcelData.getDate(), k -> new HashMap<>())
                                .computeIfAbsent(orderExcelData.getBuyer(), k -> new ArrayList<>())
                                .add(orderExcelData));
            }
        }

        Map<String, GoodExcelData> goodExcelDataMap = new HashMap<>();

        ExcelUtil.readDo(path, FileConstant.GOODS_SHEET_NAME, GoodExcelData.class,
                data -> true,
                data -> goodExcelDataMap.put(data.getGoods(), data));


        startToPdf(dateOrderMap, goodExcelDataMap);
    }

    private void startToPdf(Map<Date, Map<String, List<OrderExcelData>>> dateOrderMap, Map<String, GoodExcelData> goodExcelDataMap) {
        boolean error = false;

        for (Map.Entry<Date, Map<String, List<OrderExcelData>>> dateMapEntry : dateOrderMap.entrySet()) {
            Date key = dateMapEntry.getKey();
            for (Map.Entry<String, List<OrderExcelData>> buyer2OrderEntry : dateMapEntry.getValue().entrySet()) {
                String buyer = buyer2OrderEntry.getKey();
                List<OrderExcelData> dataList = buyer2OrderEntry.getValue();

                String address = getStoreNameByBuyer(buyer);

                try {
                    String filePath = String.format("prototype%s%s", dataList.size(), FileConstant.WORD_FILE_SUFFIXES);
                    File file = new File(filePath);
                    // 没有模板文件 生成模板文件
                    if(!file.exists()){
                        WordUtil.generatePrototype("prototype1" + FileConstant.WORD_FILE_SUFFIXES, filePath,
                                dataList.size(), FileConstant.ORDER_PDF_TABLE_START_INDEX);
                    }

                    InputStream resourceAsStream = new FileInputStream(filePath);


                    List<String> params = getOrderParams(key, goodExcelDataMap, dataList);

                    String targetName = String.format("%s\\%s-%s-%s", targetPath, DateUtils.format(key, DateConstant.DATE_FORMAT_0), buyer, address);
                    WordUtil.translateWordToPNGWithParam(resourceAsStream,
                            targetName,
                            params);

                    resourceAsStream.close();

                } catch (Exception e) {
                    e.printStackTrace();

                    if (error) {
                        continue;
                    }

                    showErrorMessageDialog(e);
                    error = true;
                }
            }
        }

        if (error) {
            return;
        }

        JOptionPane.showMessageDialog(this,
                "生成完成", "tip", JOptionPane.INFORMATION_MESSAGE);
    }

    private void showErrorMessageDialog(Exception e) {
        JOptionPane.showMessageDialog(this,
                "错误：" + e.getCause(), "error", JOptionPane.ERROR_MESSAGE);
    }

    private java.util.List<String> getOrderParams(Date date, Map<String, GoodExcelData> goodExcelDataMap, java.util.List<OrderExcelData> dataList) {
        List<String> params = new ArrayList<>();

        OrderExcelData first = dataList.get(0);

        params.add(getStoreNameByBuyer(first.getBuyer()));
        params.add(first.getBuyer());
        params.add(DateUtils.format(date, DateConstant.DATE_FORMAT));

        float allPrice = 0;

        for (int i = 0; i < dataList.size(); i++) {
            OrderExcelData orderExcelData = dataList.get(i);

            params.add(String.valueOf(i + 1));
            params.add(orderExcelData.getGoods());

            GoodExcelData goodExcelData = goodExcelDataMap.get(orderExcelData.getGoods());
            params.add(goodExcelData == null ? "" : goodExcelData.getStandards());

            params.add(String.format("%.2f", orderExcelData.getWeight()));
            params.add(String.format("%.2f", orderExcelData.getOriginPride()));

            float finalPrice = orderExcelData.getWeight() * orderExcelData.getOriginPride();
            params.add(String.format("%.2f", finalPrice));

            params.add(goodExcelData == null ? "" : goodExcelData.getRemark());

            allPrice += finalPrice;
        }

        params.add(String.format("%.2f", allPrice));
        return params;
    }

    private void settle() {
        Map<String, List<OrderExcelData>> target = new HashMap<>();
        // 选中的数据
        selectBox.walkSelectedValues(address -> {
            List<OrderExcelData> orderExcelDatum = address2OrderExcelDataList.get(address);
            if (CollectionUtils.isEmpty(orderExcelDatum)) {
                return;
            }
            orderExcelDatum.forEach(orderExcelData ->
                    target.computeIfAbsent(getStoreNameByBuyer(orderExcelData.getBuyer()), k -> new ArrayList<>()).add(orderExcelData));
        });

        Map<String, GoodExcelData> goodExcelDataMap = new HashMap<>();

        ExcelUtil.readDo(path, FileConstant.GOODS_SHEET_NAME, GoodExcelData.class,
                goodExcelData -> true,
                goodExcelData -> goodExcelDataMap.put(goodExcelData.getGoods(), goodExcelData));

        // 没有选就尝试拿全部
        if (MapUtils.isEmpty(target)) {
            settleToPdf(address2OrderExcelDataList, goodExcelDataMap);

        } else {
            settleToPdf(target, goodExcelDataMap);

        }
    }

    private void settleToPdf(Map<String, List<OrderExcelData>> target, Map<String, GoodExcelData> goodExcelDataMap) {
        boolean error = false;

        for (Map.Entry<String, List<OrderExcelData>> address2DataList : target.entrySet()) {
            String address = address2DataList.getKey();
            List<OrderExcelData> dataList = address2DataList.getValue();
            String buyer = dataList.get(0).getBuyer();

            try {
                String filePath = String.format("month%s%s", dataList.size(), FileConstant.WORD_FILE_SUFFIXES);
                File file = new File(filePath);
                // 没有模板文件 生成模板文件
                if(!file.exists()){
                    WordUtil.generatePrototype("month1" + FileConstant.WORD_FILE_SUFFIXES, filePath,
                            dataList.size(), FileConstant.SETTLE_PDF_TABLE_START_INDEX);
                }

                InputStream resourceAsStream = new FileInputStream(filePath);

                List<String> params = getSettleParams(goodExcelDataMap, dataList);

                String targetName = String.format("%s\\%s-%s", targetPath, buyer, address);
                WordUtil.translateWordToPNGWithParam(resourceAsStream,
                        targetName,
                        params);

                resourceAsStream.close();

            } catch (Exception e) {
                e.printStackTrace();

                if (error) {
                    continue;
                }

                JOptionPane.showMessageDialog(this,
                        "错误：" + e.getCause(), "error", JOptionPane.ERROR_MESSAGE);
                error = true;
            }
        }

        if (error) {
            return;
        }

        JOptionPane.showMessageDialog(this,
                "生成完成", "tip", JOptionPane.INFORMATION_MESSAGE);

    }

    private List<String> getSettleParams(Map<String, GoodExcelData> goodExcelDataMap, List<OrderExcelData> dataList) {
        List<String> params = new ArrayList<>();

        OrderExcelData first = dataList.get(0);

        params.add(getStoreNameByBuyer(first.getBuyer()));
        params.add(first.getBuyer());

        float allPrice = 0;

        for (int i = 0; i < dataList.size(); i++) {
            OrderExcelData orderExcelData = dataList.get(i);

            params.add(String.valueOf(i + 1));
            params.add(DateUtils.format(orderExcelData.getDate(), DateConstant.DATE_FORMAT_0));
            params.add(orderExcelData.getGoods());

            GoodExcelData goodExcelData = goodExcelDataMap.get(orderExcelData.getGoods());
            params.add(goodExcelData == null ? "" : goodExcelData.getStandards());

            params.add(String.format("%.2f", orderExcelData.getWeight()));
            params.add(String.format("%.2f", orderExcelData.getOriginPride()));

            float finalPrice = orderExcelData.getWeight() * orderExcelData.getOriginPride();
            params.add(String.format("%.2f", finalPrice));

            allPrice += finalPrice;
        }

        params.add(String.format("%.2f", allPrice));
        return params;
    }

    private boolean checkTime() {
        if (date == null) {
            return true;
        }


        if (date1 == null) {
            return true;
        }

        return date.getTime() <= date1.getTime();
    }
}
